#include <stdint.h>
#include "config.h"
#include "apitrans.h"
#include "result.h"
#include "devapi.h"



#define CONFIG_PATH    "/appfs/"

//#define O_CREAT 0x0200
#if defined (_SUPPORT_FILE_OPER)      

static int api_file_open(unsigned char *cmd, int len)
{
	uint8_t name_len;
	char file_name[256]={0};
	int mod = 0;
	uint32_t ret ;
	uint8_t offset = 0;
	int fd ;
	mod = cmd[offset];
	offset += 1;
	name_len = cmd[offset];
	offset += 1;
	memcpy(file_name, CONFIG_PATH ,strlen(CONFIG_PATH));
	memcpy(file_name + strlen(CONFIG_PATH), cmd + offset, name_len);
	offset += name_len;
	if(offset != len){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	if(mod & 0x04){
		mod = mod | O_CREAT;
	}
	fd = open(file_name,mod);
debug_aux("%s(), %d :", __func__, __LINE__); 
debug_aux("file_name = %s(),mod = %d\r\n", file_name, mod); 
    
	if(fd < 0){
		ret = FILE_ERR_CODE(fd);
		memcpy(cmd,&ret,2);
		return -1;
	}
	else
		ret = DEAL_SUCCESS;
	offset = 0;
	memcpy(cmd,&ret,2);
	offset += 2;
	DectoBCD(fd,cmd+offset,4);
	offset += 4;
	return offset;
}

static int api_file_close(unsigned char *cmd, int len)
{
	int fd = 0;
	uint16_t ret = DEAL_SUCCESS;
	uint8_t offset = 0;
	fd = BCDtoDec(cmd,4);
	offset += 4;
	if(offset != len){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	
	fd = close(fd);
	if(fd < 0){
		ret = FILE_ERR_CODE(fd);
		memcpy(cmd,&ret,2);
		return -1;
	}
	offset = 0;
	memcpy(cmd,&ret,2);
	offset += 2;
	return offset;
	
}

static int api_file_read(unsigned char *cmd, int inlen)
{
	uint32_t fd = 0;
	int len;
	uint16_t ret = DEAL_SUCCESS;
	char buffer[MAX_SIZE];
	uint16_t offset = 0;
	fd = BCDtoDec(cmd+offset,4);
	offset += 4;
	len = BCDtoDec(cmd+offset,2);
	if(len > MAX_SIZE){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	offset += 2;
	if(offset != inlen || len>MAX_SIZE){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	len = read(fd,buffer,len);
debug_aux("%s(), %d :", __func__, __LINE__); 
debug_aux_hex("", (uint8_t*)buffer, len);         
	if(len < 0){
		ret = FILE_ERR_CODE(len);
		memcpy(cmd,&ret,2);
		return -1;
	}
	offset = 0;
	memcpy(cmd,&ret,2);
	offset +=2;
	DectoBCD(len,cmd+offset,2);
	offset +=2;
	memcpy(cmd+offset,buffer,len);
	offset += len;
	return offset;
	
}

static int api_file_write(unsigned char *cmd, int inlen)
{
	uint32_t fd = 0;
	int len;
	uint16_t ret;
	char buffer[MAX_SIZE];
	int offset = 0;
	fd = BCDtoDec(cmd+offset,4);
	offset += 4;
	len = BCDtoDec(cmd+offset,2);
	offset += 2;
	if(len > MAX_SIZE){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	memcpy(buffer,cmd+offset,len);
	offset += len;
	if(offset != inlen || (len > MAX_SIZE)){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
debug_aux("%s(), %d :", __func__, __LINE__); 
debug_aux_hex("", (uint8_t*)buffer, len);            
	len  = write(fd,buffer,len);
	if(len < 0){
		ret = FILE_ERR_CODE(len);
		memcpy(cmd,&ret,2);
		return -1;
	}
	else
		ret = DEAL_SUCCESS;	
	offset = 0;
	memcpy(cmd,&ret,2);
	offset += 2;
	DectoBCD(len,cmd+offset,2);
	offset += 2;
	return offset;
}

static int api_file_lseek(unsigned char *cmd, int len)
{
	uint32_t fd = 0;
	int offset;
	uint8_t mod;
	uint16_t ret;
	int cur_seek = -1;
	int offset1 = 0;
	fd = BCDtoDec(cmd,4);
	offset1 += 4;
	offset = BCDtoDec(cmd+offset1,4);
	offset1 += 4;
	mod = cmd[offset1++];
	if(offset1 != len){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	switch(mod){
		case 0x00:
			cur_seek = lseek(fd,offset,SEEK_SET);
			break;
		case 0x01:
			cur_seek = lseek(fd,-offset,SEEK_CUR);
			break;
		case 0x02:
			cur_seek = lseek(fd,offset,SEEK_CUR);
			break;
		case 0x03:
			cur_seek = lseek(fd,-offset,SEEK_END);
			break;
		default:
			break;
	}
	if(cur_seek < 0){
		ret = FILE_ERR_CODE(cur_seek);
		memcpy(cmd,&ret,2);
		return -1;
	}
	else{
		ret = DEAL_SUCCESS;
	}
	offset1 = 0;
	memcpy(cmd,&ret,2);
	offset1 +=2;
	DectoBCD(cur_seek,cmd+offset1,4);
	offset1 +=4;
	return offset1;
}

static int api_file_unlink(unsigned char *cmd, int len)
{
	uint8_t name_len;
	char file_name[20]={0};
	uint16_t ret = DEAL_SUCCESS ;
	uint8_t offset = 0;
	int ret1 = 0;
	name_len = cmd[offset++];
	memcpy(file_name, CONFIG_PATH ,strlen(CONFIG_PATH));
	memcpy(file_name + strlen(CONFIG_PATH), cmd+offset, name_len);
	offset += name_len;
	if(offset != len){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	ret1 = unlink(file_name);
debug_aux("%s(), %d :", __func__, __LINE__); 
debug_aux("file_name = %s(),ret1 = %d\r\n", file_name, ret1);     
	if(ret1 < 0){
		ret = FILE_ERR_CODE(ret1);
		memcpy(cmd,&ret,2);
		return -1;
	}
	offset = 0;
	memcpy(cmd,&ret,2);
	offset +=2 ;
	return sizeof(uint16_t);
}

static int file_get_size(unsigned char *cmd, int inlen)
{
	int fd = 0;
	uint8_t name_len;
	char file_name[256];
	uint16_t ret = DEAL_SUCCESS ;
	uint8_t offset = 0;
	int size = 0;;
	name_len = cmd[offset++];
	memcpy(file_name, CONFIG_PATH ,strlen(CONFIG_PATH));
	memcpy(file_name + strlen(CONFIG_PATH), cmd+offset, name_len);
	offset += name_len;
	if(offset != inlen){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	if((fd = open(file_name,O_RDONLY))<0){
		ret = FILE_ERR_CODE(fd);
		memcpy(cmd, &ret, 2);
		return -1;
	}
	size = lseek( fd, 0, SEEK_END) - lseek( fd, 0, SEEK_SET);
	close(fd);
	offset = 0;
	memcpy(cmd, &ret, 2);
	offset += 2;
	DectoBCD(size,cmd+offset,4);
	offset += 4;
	return offset;
}

static func_t file_fun[] = {
	NULL, api_file_open, api_file_close, api_file_read, \
		 api_file_write,api_file_lseek,api_file_unlink,file_get_size
};

int cmd_file(uint8_t cmd,uint8_t *buf, int len)
{
	if(cmd < 0x01 || cmd > FUN_SIZE(file_fun))
		return -5;
	return file_fun[(int)cmd]((uint8_t*)buf,len);
}

#endif

